home *** CD-ROM | disk | FTP | other *** search
/ Crack It! / Crack It!.iso / CONTENT / JSTEST / JST300D.EXE / STICKRT.ASM < prev    next >
Encoding:
Assembly Source File  |  1996-10-01  |  10.0 KB  |  240 lines

  1. ;***
  2. ;
  3. ;STICKRT.ASM
  4. ;Turbo Pascal Joystick Interface Module
  5. ;(C)Copyright Gerard Paul Java 1996
  6.  
  7. ;Interface Source File
  8. ;
  9. ;This file contains joystick routines for use by Turbo Pascal 5.0 and later
  10. ;programs.  These provide Pascal with a joystick interface.  The StickCoord
  11. ;and StickButtonDown routines are to be declared in Pascal as functions as:
  12. ;
  13. ;    function StickCoord(AxisCode: byte): byte; external;
  14. ;    function StickButtonDown(ButtonCode: byte): boolean; external;
  15. ;
  16. ;For StickCoord, pass a value of 1 for the X-coordinate of stick A, 2 for
  17. ;the Y-coordinate of stick A, 4 for the X-coordinate of stick B, 16 for the
  18. ;Y-coordinate of stick B.
  19. ;
  20. ;For StickButtonDown, pass a value of 16 for button 1 on stick A, 32 for
  21. ;button 2 on stick A, 64 for button 1 on stick B, 128 for button 2 on stick
  22. ;B.  Returns TRUE if the button is up, FALSE if pressed.
  23. ;
  24. ;Assemble with the Borland Turbo Assembler 1.0 or later.
  25. ;
  26. ;This module is designed to be linked into Turbo Pascal units, and these
  27. ;routines are intended to be declared in the interface sections.  The
  28. ;routines therefore make use of the FAR call model.
  29.  
  30. ;Note to programmers: arguments passed from Pascal correspond to the bit
  31. ;values involved.  Therefore, when the StickCoord function takes 4 for its
  32. ;argument, it checks the status of the third bit.  This is done for speed
  33. ;and efficiency.
  34. ;
  35. ;These routines access the joystick data directly from port 201H.  It does
  36. ;not make use of the BIOS INT 15h Service 84h.  These routines will therefore
  37. ;work on the PCs and XTs.  However, this also requires that the computer be
  38. ;100% hardware-compatible with the PC family.
  39. ;
  40. ;This is the layout of the byte received from port 201H:
  41. ;
  42. ;                  128  64  32  16   8   4   2   1      <--- place values
  43. ;                    1   1   1   1   1   1   1   1
  44. ;                    ^   ^   ^   ^
  45. ;                    |   |   |   |
  46. ;Button B2 status ---+   |   |   |
  47. ;Button B1 status -------+   |   |
  48. ;Button A2 status -----------+   |
  49. ;Button A1 status ---------------+
  50. ;
  51. ;Each button status bit is high (1) when its respective button is up, low (0)
  52. ;when down.
  53. ;
  54. ;The remaining bits are high (1) for a certain period, depending on the
  55. ;shaft positions on their corresponding axes, after which they go low (0).
  56. ;The time during which the bits are high corresponds to the shaft positions
  57. ;on their corresponding axes.  This can be determined using a program loop.
  58. ;
  59. ;Bit 3 corresponds to axis Y2, bit 2 to axis X2, bit 1 to axis Y1, and bit 0
  60. ;to axis X1.
  61. ;
  62. ;The shaft positions increase with CPU speed.  This characteristic is
  63. ;present in all software using joysticks.  The selection for 20000 as the
  64. ;"not found" value is based on the fact that no joystick reaches that value,
  65. ;even with the fastest CPUs.
  66. ;
  67. ;The other routines have comment headers explaining their functions.
  68. ;Declare them as:
  69. ;
  70. ;    function StickIsPresent(StickCode: boolean): boolean; external;
  71. ;    procedure InitAndCheckGameSys(var ErrCode: boolean); external;
  72. ;;
  73. ;These routines will work with any device connected to the standard IBM game
  74. ;port.  Such devices must use the same technology as the IBM-compatible
  75. ;joysticks.  As much as possible, the detection routines provide for
  76. ;violation of the IBM specs, for example, if another device or adapter uses
  77. ;port 201H for purposes other than what IBM dictated.  Such conditions may
  78. ;be interpreted as error conditions, but no guarantee is given.
  79. ;
  80. ;***
  81. ;
  82.  
  83. MAXCOUNT        EQU     20000                 ;Maximum count for stick.
  84. GAMEPORT        EQU     201H                  ;Game port.
  85.  
  86. .MODEL TPASCAL                                ;Turbo Pascal interface module.
  87.  
  88. .CODE
  89.  
  90. PUBLIC          StickCoord                    ;Make routines available.
  91. PUBLIC          StickButtonDown
  92. PUBLIC          StickIsPresent
  93. PUBLIC          InitAndCheckGameSys
  94.  
  95.  
  96. ;--------------------------------------------------------------------------
  97. ;StickCoords: Returns the specified joystick position.  From Turbo Pascal,
  98. ;pass 1 for X1, 2 for Y1, 4 for X2, and 8 for Y2.
  99. ;
  100. ;Function returns word value in AX, interpreted as word from Pascal.
  101. ;Minimum return value is 0, although chances are that the minimum will
  102. ;be higher, considering the speeds of PCs nowadays.
  103. ;
  104. ;BX,CX,DX destroyed.
  105. ;--------------------------------------------------------------------------
  106.  
  107. StickCoord      PROC    FAR     AxisCode: BYTE
  108.         MOV     BL,AxisCode           ;Load parameter into BL.
  109.         MOV     CX,MAXCOUNT           ;Load max count.
  110.         MOV     DX,GAMEPORT           ;Adapter I/O data port.
  111. SETTLE_WAIT:    IN      AL,DX                 ;Wait for bit to settle.
  112.         TEST    AL,BL
  113.         LOOPNZ  SETTLE_WAIT
  114.         JCXZ    TOO_HIGH              ;Resistance too high, done.
  115.         MOV     CX,1FFH               ;Delay a bit
  116. DELAY:          JMP     SHORT $+2
  117.         JMP     SHORT $+2
  118.         JMP     SHORT $+2
  119.         LOOP    DELAY
  120.         MOV     CX,MAXCOUNT
  121.         OUT     DX,AL                 ;Start joystick timers.
  122.         CLI                           ;Interrupts off, plus settle.
  123.         XOR     CX,CX                 ;Initialize counter.
  124. TIME_STICK:     IN      AL,DX                 ;Read byte.
  125.         TEST    AL,BL                 ;Bit high?
  126.         JZ      DONE                  ;Inc CX if done, done if no.
  127.         INC     CX                    ;Increase CX
  128.         CMP     CX,MAXCOUNT           ;Resistance too high?
  129.         JE      TOO_HIGH              ;Yes, done.
  130.         JMP     SHORT $+2             ;Really big delay to stabilize.
  131.         JMP     SHORT $+2
  132.         JMP     SHORT $+2
  133.         JMP     TIME_STICK            ;Yes, loop until low or CXZ.
  134. DONE:           STI                           ;Interrupts back on.
  135.                 MOV     AX,CX                 ;Store maxcount in AX.
  136.         SHR     AX,1                  ;Divide by 2, for less vibr.
  137.         RET                           ;Return to caller.
  138. TOO_HIGH:       MOV     AX,MAXCOUNT           ;Return maxcount if error.
  139.         RET
  140. StickCoord      ENDP
  141.  
  142. ;
  143. ;---------------------------------------------------------------------------
  144. ;StickButtonDown: Returns the status of the specified button.  From Turbo
  145. ;Pascal, pass 16 or A1, 32 for A2, 64 for B1, and 128 for B2.  Returns True
  146. ;if pressed, False of up.
  147. ;
  148. ;Returns a byte value in AL, interpreted as boolean from Pascal.
  149. ;
  150. ;DX destroyed.
  151. ;--------------------------------------------------------------------------
  152. ;
  153. StickButtonDown PROC    FAR     ButtonCode: BYTE
  154.         MOV     DX,GAMEPORT           ;Point to game port.
  155.         IN      AL,DX                 ;Read joystick.
  156.         TEST    AL,ButtonCode         ;Bit high?
  157.         JNZ     NOT_PRESSED           ;Yeah, not pressed
  158.         MOV     AL,1                  ;else pressed, return True.
  159.         RET                           ;Return to caller.
  160. NOT_PRESSED:    XOR     AL,AL                 ;Return False if button up.
  161.         RET                           ;Return to caller.
  162. StickButtonDown ENDP
  163.  
  164.  
  165. ;--------------------------------------------------------------------------
  166. ;StickIsPresent: Determines whether the specified stick is present.  If any
  167. ;or both of the resistive inputs stay high for too long, or if from low,
  168. ;suddenly go high without signalling, it indicates an absence of the stick.
  169. ;
  170. ;Pass 0201H to check for stick A, 0804H to check for stick B.
  171. ;
  172. ;Returns a byte value in AL, interpreted as boolean from Pascal.
  173. ;
  174. ;BX,CX,DX destroyed.
  175. ;--------------------------------------------------------------------------
  176.  
  177. StickIsPresent  PROC    FAR     TestBy: WORD
  178. TEST_X_AXIS:    MOV     BX,TestBy             ;Load detection parameter.
  179.         MOV     CX,MAXCOUNT           ;Max count
  180.         MOV     DX,GAMEPORT           ;Load in port address.
  181.         OUT     DX,AL                 ;Start 558/556 one-shots.
  182. READ_PORT1:     IN      AL,DX                 ;Read adapter.
  183.         TEST    AL,BL                 ;Low?
  184.         LOOPNZ  READ_PORT1            ;No, loop till so.
  185.         JCXZ    TEST_Y_AXIS           ;High too long; try Y axis.
  186.         JMP     STICK_PRESENT         ;Gone low, must be present.
  187. TEST_Y_AXIS:    MOV     CX,MAXCOUNT           ;Reload max count.
  188.         OUT     DX,AL                 ;Restart one-shots.
  189. READ_PORT2:     IN      AL,DX                 ;Read adapter.
  190.         TEST    AL,BH                 ;Low?
  191.         LOOPNZ  READ_PORT2            ;Loop until so.
  192.         JCXZ    STICK_ABSENT          ;Still high, error.
  193. STICK_PRESENT:  MOV     AL,1
  194.         RET
  195. STICK_ABSENT:   XOR     AL,AL
  196.         RET
  197. StickIsPresent  ENDP
  198.  
  199.  
  200. ;---------------------------------------------------------------------------
  201. ;This procedure tests whether there are any game devices attached to the
  202. ;PC.  If an adapter is present, the bits don't go low if their corresponding
  203. ;joysticks are not present, so if this happens, the joystick is absent.
  204. ;If they do go low, another check is conducted to see if any of them go high
  205. ;even if not triggered.  If they do, the adapter is not present, and
  206. ;therefore, no joysticks.
  207. ;
  208. ;Returns a byte value in a variable parameter, interpreted as boolean from
  209. ;Pascal.
  210. ;
  211. ;AX,CX,DX destroyed.
  212. ;---------------------------------------------------------------------------
  213.  
  214. InitAndCheckGameSys     PROC    FAR     ErrCodeAddr: DWORD
  215.         LES     DI,ErrCodeAddr
  216.         MOV     DX,GAMEPORT          ;Game adapter I/O.
  217.         MOV     CX,MAXCOUNT          ;Load count.
  218.         OUT     DX,AL                ;Start one-shots.
  219. CHECK_STICKS:   IN      AL,DX                ;Read adapter.
  220.         AND     AL,0FH               ;Zero upper bits.
  221.         CMP     AL,0FH               ;Check for changes.
  222.         LOOPE   CHECK_STICKS         ;Loop while none.
  223.         JCXZ    NEG_CHECK            ;Still high, error.
  224.         MOV     CX,MAXCOUNT          ;Reload count.
  225.         MOV     BL,AL                ;Transfer last bits to BL.
  226. RECHECK:        IN      AL,DX                ;Reread port.
  227.         AND     AL,0FH
  228.         CMP     AL,BL                ;Changes?
  229.         LOOPE   RECHECK              ;Loop while none.
  230.         JCXZ    OK                   ;No changes since, ok.
  231.         JB      OK                   ;Changes, from high to low, ok.
  232. NEG_CHECK:      MOV     BYTE PTR ES:[DI],01  ;But from low to high, no way.
  233.         RET
  234. OK:             MOV     BYTE PTR ES:[DI],00  ;No error return 0, 1 otherwise.
  235.         RET
  236. InitAndCheckGameSys     ENDP
  237.  
  238.         END
  239.  
  240.